package sinffier

import (
	"config"
	"fmt"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"gopkg.in/mgo.v2"
	"log"
	"regexp"
	"sinffier/types"
	"strings"
	"time"
)

var (
	device      string = "lo0"
	snapshotLen int32  = 1024
	promiscuous bool   = false
	err         error
	timeout     time.Duration = 30 * time.Second
	handle      *pcap.Handle
)

func Run() {
	// Open device
	handle, err = pcap.OpenLive(device, snapshotLen, promiscuous, timeout)
	if err != nil {
		log.Fatal(err)
	}
	defer handle.Close()

	// Set filter
	var filter string = "tcp and port 3306"
	err = handle.SetBPFFilter(filter)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Only capturing TCP port 3306 packets.")

	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	for packet := range packetSource.Packets() {
		printPacketInfo(packet)
	}
}

func printPacketInfo(packet gopacket.Packet) {

	session, err := mgo.Dial(config.MONGO_HOST)
	if err != nil {
		panic(err)
	}
	defer session.Close()
	session.SetMode(mgo.Monotonic, true)

	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer == nil {
		panic("解析IP地址错误")
	}
	applicationLayer := packet.ApplicationLayer()
	if applicationLayer != nil {
		payload := applicationLayer.Payload()
		contents := string(payload[:])

		r, _ := regexp.Compile("(?i:select|insert|update|delete)")
		if r.MatchString(contents) {
			ip, _ := ipLayer.(*layers.IPv4)
			form := fmt.Sprintf("From %s to %s\n", ip.SrcIP, ip.DstIP)
			query := contents[1:]
			nowTime := time.Now().Unix()
			collection := session.DB(config.DB_NAME).C("mysql")
			err = collection.Insert(&types.Mysql{"mysql", strings.TrimSpace(query), form, nowTime})
			if err != nil {
				log.Fatal(err)
			} else {
				fmt.Printf("Date %s insert logs success.\n", time.Now().Format("2006-01-02 15:04:05"))
			}
		}

		if strings.Contains(string(applicationLayer.Payload()), "HTTP") {
			fmt.Println("HTTP found!")
		}
	}

	// Check for errors
	if err := packet.ErrorLayer(); err != nil {
		fmt.Println("Error decoding some part of the packet:", err)
	}
}
